package com.heaven.jane.sourcegenerator.util;

import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.heaven.jane.sourcegenerator.business.module.domain.Module;
import com.heaven.jane.sourcegenerator.commons.constant.CodeType;
import com.heaven.jane.sourcegenerator.commons.constant.TemplateCreateType;
import com.heaven.jane.sourcegenerator.commons.constant.TemplateType;

import org.springframework.util.StringUtils;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;
import lombok.Builder;
import lombok.extern.slf4j.Slf4j;

/**
 * 代码生成执行入口
 * 
 * @author heaven
 *
 */
@Slf4j
@Builder
public class CodeGenerator {

	@Builder.Default
	private Configuration cfg = new Configuration(Configuration.VERSION_2_3_22);

	/**
	 * 生成模块代码
	 * 
	 * @param modules      需要生成代码模块列表
	 * @param basePath     生成项目根路径
	 * @param templateType 模板类型
	 * @param codeType     代码类型
	 * @throws IOException
	 * @throws TemplateException
	 */
	public void generator(List<Module> modules, String basePath, TemplateType templateType, CodeType codeType)
			throws IOException, TemplateException {
		cfg.setDirectoryForTemplateLoading(codeType.getTemplate().getFile());
		cfg.setDefaultEncoding("UTF-8");
		cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);

		Template template = cfg.getTemplate(templateType.getName());

		if (TemplateCreateType.覆盖原文件.equals(templateType.getCreateType())) {
			FileWriter out;
			try {
				Map<String, Object> root = new HashMap<String, Object>();
				root.put("modules", modules);
				out = new FileWriter(generatorfilePath(templateType, basePath));
				template.process(root, out);
			} catch (IOException e) {
				log.error("", e);
			} catch (TemplateException e) {
				log.error("", e);
			}
		} else {
			modules.stream().forEach(module -> {
				FileWriter out;
				try {
					out = new FileWriter(generatorfilePath(templateType, module, basePath));
					template.process(module, out);
				} catch (IOException e) {
					log.error("", e);
				} catch (TemplateException e) {
					log.error("", e);
				}
			});
		}
	}

	private String generatorfilePath(TemplateType templateType, String basePath) {
		return basePath + templateType.getTargetDir();
	}

	private String generatorfilePath(TemplateType templateType, Module module, String basePath) throws IOException {
		String filePath = null;
		if (TemplateCreateType.创建目录及文件.equals(templateType.getCreateType())) {
			if (TemplateType.前端视图模块模板.equals(templateType)) {
				filePath = basePath + templateType.getTargetDir().replace("${module}", module.getName())
						+ templateType.getSuffix();
			} else {
				filePath = basePath + templateType.getTargetDir().replace("${module}", module.getName())
						+ StringUtils.capitalize(module.getName()) + templateType.getSuffix();
			}
		} else {
			filePath = basePath + templateType.getTargetDir() + module.getName() + templateType.getSuffix();
		}

		Path path = Paths.get(filePath);
		if (!Files.exists(path.getParent())) {
			Files.createDirectories(path.getParent());
		}
		return filePath;
	}

}
